<?php
namespace fakis\enum;

use yii\helpers\ArrayHelper;

/**
 * 字典通用性解决方案.
 * Trait EnumTrait
 *
 * 给类提供定义一系列字典特性，以及为处理字典提供一系列方法.
 * 定义字典结构为：`['字典名称' => ['索引' => '标签']]`.
 *
 * Usage
 *
 * ```php
 * use fakis\enum\EnumTrait;
 *
 * class User extends ActiveRecord implements EnumInterface
 * {
 *     use EnumTrait;
 *
 *     const STATUS_ACTIVATED = 1;
 *     const STATUS_INACTIVATED = 2;
 *
 *     const GENDER_MALE = 1;
 *     const GENDER_FEMALE = 2;
 *
 *     public static function enums()
 *     {
 *         return [
 *             'status' => [
 *                 self::STATUS_ACTIVATED => Yii::t('app', '已激活'),
 *                 self::STATUS_INACTIVATED => Yii::t('app', '未激活'),
 *             ],
 *             'gender' => [
 *                 self::GENDER_MALE => Yii::t('app', '男'),
 *                 self::GENDER_FEMALE => Yii::t('app', '女'),
 *             ],
 *         ];
 *     }
 * }
 *
 * User::getEnumsByLabel('gender');
 * User::getEnumsByIndex('status');
 * User::getEnumLabel('gender', User::GENDER_MALE);
 * User::getEnumIndex('status', '未激活');
 * ```
 *
 * @package fakis\enum
 * @author Fakis <fakis738@qq.com>
 */
trait EnumTrait
{
    /**
     * @var array
     */
    private static $_enums = [];

    /**
     * @return array
     */
    private static function uniqueEnums()
    {
        $class = get_called_class();
        if (!isset(self::$_enums[$class])) {
            self::$_enums[$class] = static::enums();
        }
        return self::$_enums[$class];
    }

    /**
     * @return array
     */
    public static function enums()
    {
        return [];
    }

    /**
     * 取得字典名是否在字典中定义
     * @param string $name
     * @return bool
     */
    public static function hasEnums($name)
    {
        $enums = self::uniqueEnums();
        return !empty($enums[$name]) && is_array($enums[$name]);
    }

    /**
     * 返回字典列表
     * @param string $name 字典名
     * @return array
     */
    public static function getEnums($name)
    {
        return self::hasEnums($name) ? ArrayHelper::getValue(self::uniqueEnums(), $name, []) : [];
    }

    /**
     * 返回字典列表（标签为值）
     * @param string $name 字典名
     * @return array
     */
    public static function getEnumsByLabel($name)
    {
        return self::getEnums($name);
    }

    /**
     * 返回字典列表（索引为值）
     * @param string $name 字典名
     * @return array
     */
    public static function getEnumsByIndex($name)
    {
        return array_flip(self::getEnums($name));
    }

    /**
     * 标签在字典列表中是否存在
     * @param string $name 字典名
     * @param string $label 标签
     * @return bool
     */
    public static function hasEnumLabel($name, $label)
    {
        return array_key_exists($label, self::getEnumsByIndex($name));
    }

    /**
     * 索引值在字典列表中是否存在
     * @param string $name 字典名
     * @param string $index 索引值
     * @return bool
     */
    public static function hasEnumIndex($name, $index)
    {
        return array_key_exists($index, self::getEnumsByLabel($name));
    }

    /**
     * 根据索引值取得字典标签
     * @param string $name 字典名
     * @param string $index 索引值
     * @param mixed $default 默认值
     * @return mixed
     */
    public static function getEnumLabel($name, $index, $default = null)
    {
        return ArrayHelper::getValue(self::getEnumsByLabel($name), $index, $default);
    }

    /**
     * 根据标签取得字典索引值
     * @param string $name 字典名
     * @param string $label 标签
     * @return string|null|mixed
     */
    public static function getEnumIndex($name, $label)
    {
        return ArrayHelper::getValue(self::getEnumsByIndex($name), $label);
    }
}
